package com.ssmr.demo.service;

import com.ssmr.demo.entity.SeckillStatus;
import com.ssmr.demo.entity.TProduct;
import com.ssmr.demo.entity.TPurchaseRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Service
public class SeckillServiceImpl implements SeckillService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private TUserService tUserService;
    @Autowired
    private TProductService tProductService;
    @Autowired
    private RabbitmqProducerService rabbitmqProducerService;

    private SeckillStatus seckillStatus;
    private static final String SECKILL_PREFIX = "seckill_";

    @Override
    public int seckill(Integer idtUser, Integer idtProduct, Integer quantity) {

        /*pipeline批量发送命令，可以提高性能，但是必须返回Null*/
      /* redisTemplate.executePipelined(new SessionCallback<Object>() {
           @Override
           public <K, V> Object execute(RedisOperations<K, V> redisOperations) throws DataAccessException {
               return null;
           }
       });*/

        Object executeResult = redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations redisOperations) throws DataAccessException {
                ArrayList<String> arrayList = new ArrayList<>();
                arrayList.add("idtProduct");
                arrayList.add("product_name");
                arrayList.add("stock");
                arrayList.add("price");
                arrayList.add("version");
                List list = redisOperations.opsForHash().multiGet(SECKILL_PREFIX + String.valueOf(idtProduct), arrayList);
                String version = SECKILL_PREFIX + String.valueOf(idtProduct) + "_version";
                redisOperations.watch(version);
                int stock = Integer.parseInt((String) list.get(2));
                if (stock - quantity >= 0) {
                    /*这个list里存放的应该是JSON格式的字符串，所以后面会有BigDecimal转换错误，因为多了双引号*/
                    list.set(2, String.valueOf(stock - quantity));
                    list.set(4, String.valueOf(Integer.parseInt((String) list.get(4)) + 1));
                    HashMap<String, String> hashMap = new HashMap<>();
                    hashMap.put("idtProduct", (String) list.get(0));
                    hashMap.put("product_name", (String) list.get(1));
                    hashMap.put("stock", (String) list.get(2));
                    hashMap.put("price", (String) list.get(3));
                    hashMap.put("version", (String) list.get(4));
                    redisOperations.multi();
                    /*好像非string不能增减*/
                    redisOperations.opsForValue().increment(version, 1);
                    redisOperations.opsForHash().putAll(SECKILL_PREFIX + idtProduct, hashMap);
                    redisOperations.opsForHash().multiGet(SECKILL_PREFIX + String.valueOf(idtProduct), arrayList);
                    List execResult = redisOperations.exec();
                    return execResult;
                } else {
                    return null;
                }
            }
        });
        /*新建用户购买记录，发送到Rabbitmq，数据库异步写入记录的部分稍后写*/
        if (executeResult == null) {
            return SeckillStatus.SECKILL_FAIL.getInteger();
        } else {
            List<Object> listResult = (List) executeResult;
//            System.out.println("返回的executeResult第一个返回了啥： " + listResult.get(0));
            List result = (List<String>) listResult.get(1);
            /*Hash value 设置的serializer 使用json, 不是string, 单纯String数据结构的value用的string, 见RedisConfig*/
            String a = String.valueOf(result.get(0));
            String b = String.valueOf(result.get(1));
            String c = String.valueOf(result.get(2));
            String d = String.valueOf(result.get(3));
            String e = String.valueOf(result.get(4));
//            System.out.println("a,b,c,d,e: " + a + " " + b + " " + c + " " + d + " " + e);
            /*例如d,price是14.89, 这里的String d 是 "14.89" 带双引号的，醉了*/
            /*Double priceDouble = Double.parseDouble(d);
            System.out.println("priceDouble: "+priceDouble);*/
            d = d.substring(1, d.length()-1);
//            System.out.println(d);
            BigDecimal price = new BigDecimal(d);
            BigDecimal totalprice = price.multiply(new BigDecimal(String.valueOf(quantity)));
            TPurchaseRecord tPurchaseRecord = new TPurchaseRecord(idtUser,idtProduct, quantity, price, totalprice, new Date());
            rabbitmqProducerService.sendPurchaseRecord(tPurchaseRecord);
            return SeckillStatus.SECKILL_SUCCESS.getInteger();
        }
    }

    @Override
    public void reCacheProducts() {

    }



}
